using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace MoEngine
{
    public struct Vector2Int : IEquatable<Vector2Int>
    {
        public int X;
        public int Y;

        public Vector2Int(int x, int y)
        {
            X = x;
            Y = y;
        }

        public Vector2Int(int value)
        {
            X = Y = value;
        }

        // Summary:
        //     Returns a vector pointing in the opposite direction.
        //
        // Parameters:
        //   value:
        //     Source vector.
        //
        // Returns:
        //     Vector pointing in the opposite direction.
        public static Vector2Int operator -(Vector2Int value)
        {
            return new Vector2Int(-value.X, -value.Y);
        }
        //
        // Summary:
        //     Subtracts a vector from a vector.
        //
        // Parameters:
        //   value1:
        //     Source vector.
        //
        //   value2:
        //     source vector.
        //
        // Returns:
        //     Result of the subtraction.
        public static Vector2Int operator -(Vector2Int value1, Vector2Int value2)
        {
            return new Vector2Int(value1.X - value2.X, value1.Y - value2.Y);
        }
        //
        // Summary:
        //     Tests vectors for inequality.
        //
        // Parameters:
        //   value1:
        //     Vector to compare.
        //
        //   value2:
        //     Vector to compare.
        //
        // Returns:
        //     Returns true if the vectors are not equal, false otherwise.
        public static bool operator !=(Vector2Int value1, Vector2Int value2)
        {
            return value1.X != value2.X || value1.Y != value2.Y;
        }
        //
        // Summary:
        //     Multiplies a vector by a scalar value.
        //
        // Parameters:
        //   scaleFactor:
        //     Scalar value.
        //
        //   value:
        //     Source vector.
        //
        // Returns:
        //     Result of the multiplication.
        public static Vector2Int operator *(float scaleFactor, Vector2Int value)
        {
            return new Vector2Int((int)Math.Round(value.X * scaleFactor), (int)Math.Round(value.Y * scaleFactor));
        }

        public static Vector2Int operator *(int scaleFactor, Vector2Int value)
        {
            return new Vector2Int(value.X * scaleFactor, value.Y * scaleFactor);
        }
        //
        // Summary:
        //     Multiplies a vector by a scalar value.
        //
        // Parameters:
        //   value:
        //     Source vector.
        //
        //   scaleFactor:
        //     Scalar value.
        //
        // Returns:
        //     Result of the multiplication.
        public static Vector2Int operator *(Vector2Int value, float scaleFactor)
        {
            return new Vector2Int((int)Math.Round(value.X * scaleFactor), (int)Math.Round(value.Y * scaleFactor));
        }
        public static Vector2Int operator *(Vector2Int value, int scaleFactor)
        {
            return new Vector2Int(value.X * scaleFactor, value.Y * scaleFactor);
        }

        //
        // Summary:
        //     Divides a vector by a scalar value.
        //
        // Parameters:
        //   value1:
        //     Source vector.
        //
        //   divider:
        //     The divisor.
        //
        // Returns:
        //     The source vector divided by b.
        public static Vector2Int operator /(Vector2Int value1, int divider)
        {
            return new Vector2Int(value1.X / divider, value1.Y / divider);
        }

        //
        // Summary:
        //     Adds two vectors.
        //
        // Parameters:
        //   value1:
        //     Source vector.
        //
        //   value2:
        //     Source vector.
        //
        // Returns:
        //     Sum of the source vectors.
        public static Vector2Int operator +(Vector2Int value1, Vector2Int value2)
        {
            return new Vector2Int(value1.X + value2.X, value1.Y + value2.Y);
        }
        //
        // Summary:
        //     Tests vectors for equality.
        //
        // Parameters:
        //   value1:
        //     Source vector.
        //
        //   value2:
        //     Source vector.
        //
        // Returns:
        //     true if the vectors are equal; false otherwise.
        public static bool operator ==(Vector2Int value1, Vector2Int value2)
        {
            return value1.X == value2.X && value1.Y == value2.Y;
        }

        public static Vector2Int operator *(Vector2Int value1, Vector2Int value2)
        {
            return new Vector2Int(value1.X * value2.X, value1.Y * value2.Y);
        }

        public override int GetHashCode()
        {
            return X ^ Y;
        }

        public override string ToString()
        {
            return string.Format("({0}, {1})", X, Y);
        }

        
        public override bool Equals(object obj)
        {
            if (obj is Vector2Int)
                return this == (Vector2Int)obj;
            else
                return false;
        }

        #region IEquatable<Vector2Int> Members

        public bool Equals(Vector2Int other)
        {
            return this == other;
        }

        #endregion

        public static implicit operator Vector2(Vector2Int vector)  
        {
            return new Vector2(vector.X, vector.Y);
        }

        public static explicit operator Vector2Int(Vector2 vector)  
        {
            return new Vector2Int((int)vector.X, (int)vector.Y);
        }

        public static float Distance(Vector2Int vector1, Vector2Int vector2)
        {
            return (float)Math.Sqrt((vector1.X - vector2.X) * (vector1.X - vector2.X) + (vector1.Y - vector2.Y) * (vector1.Y - vector2.Y));
        }
    }
}
